package com.savvy.util;

import com.savvy.exception.CodeException;

import android.os.Handler;
import android.util.Log;

public class TimerWithHandler {

	public static final int PRE_TIMER = 60;
	public static final int TIMEOUT = 61;
	public static final int PAUSED = 62;
	public static final int RESUME = 63;
	public static final int STOPPED = 64;

	public static final int ATTR_REPEAT = 0x01;
	public static final int ATTR_ONCE = 0x02;

	private Handler hOriginator;
	private long oriInterval;
	private long interval;
	private int attribute;
	private boolean pause;
	private boolean stopped;
	private Thread tmCounter;

	public TimerWithHandler(Handler handler, long interval) {
		Initialize(handler, interval, ATTR_REPEAT);
	}

	public TimerWithHandler(Handler handler, long interval, int attribute) {
		Initialize(handler, interval, attribute);
	}

	private void Initialize(Handler handler, long interval, int attribute) {
		this.hOriginator = handler;
		this.oriInterval = interval;
		this.interval = interval;
		this.attribute = attribute;
		this.pause = false;
		this.stopped = false;
	}

	public synchronized void start() throws CodeException {
		if (stopped) {
			throw new CodeException(
					"This timer has been killed, can not be restarted");
		}
		tmCounter = new Thread(new Counter());
		hOriginator.sendMessage(hOriginator
				.obtainMessage(TimerWithHandler.PRE_TIMER));
		tmCounter.start();
	}

	public synchronized boolean setPause(boolean pause) throws CodeException {
		boolean reval;
		if (stopped) {
			throw new CodeException(
					"This timer has been killed, can not be paused");
		}
		reval = this.pause;
		this.pause = pause;
		if (reval != pause) {
			if (pause == true) {
				tmCounter.interrupt();
				tmCounter = null;
				hOriginator.sendMessage(hOriginator
						.obtainMessage(TimerWithHandler.PAUSED));
				Log.v(this.getClass().toString(), "Paused");
			} else {
				hOriginator.sendMessage(hOriginator
						.obtainMessage(TimerWithHandler.RESUME));
				start();
				Log.v(this.getClass().toString(), "Restarted");
			}
		}
		return reval;
	}

	public synchronized void kill() throws CodeException {
		if (stopped) {
			throw new CodeException("Argument is error");
		}
		tmCounter.interrupt();
		tmCounter = null;
		stopped = true;
		hOriginator.sendMessage(hOriginator
				.obtainMessage(TimerWithHandler.STOPPED));
	}

	class Counter implements Runnable {
		public void run() {
			long elapsed;
			while (true) {
				Log.v(this.getClass().getName(), "sleep: " + interval);
				elapsed = System.currentTimeMillis();
				try {
					Thread.sleep(interval);
				} catch (InterruptedException e) {
					interval = System.currentTimeMillis() - elapsed;
					Log.v(this.getClass().toString(), "Remained time: "
							+ interval);
					break;
				}
				if (Thread.interrupted()) {
					interval = 0;
					Log.v(this.getClass().toString(), "Exit time: " + interval);
					break;
				}
				interval = oriInterval;
				hOriginator.sendMessage(hOriginator
						.obtainMessage(TimerWithHandler.TIMEOUT));
				Log.v(this.getClass().toString(), "alive");
				if (ATTR_ONCE == (attribute & ATTR_ONCE)) {
					break;
				}
			}
		}
	}

}
